package com.teamwings.ctrls.service.impl;

import com.auth0.jwt.JWT;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.google.common.io.Files;
import com.teamwings.common.exception.ResultException;
import com.teamwings.ctrls.FormComponent;
import com.teamwings.ctrls.service.IUploadService;
import com.teamwings.modules.code.entity.FormTableCode;
import com.teamwings.modules.code.service.IFormTableCodeService;
import com.teamwings.modules.design.vo.FormVo;
import com.teamwings.modules.head.entity.FormTableHead;
import com.teamwings.modules.head.service.IFormTableHeadService;
import com.teamwings.modules.oss.entity.OssFile;
import com.teamwings.modules.oss.service.IOssService;
import com.teamwings.util.CommonUtils;
import com.teamwings.util.VoUtils;
import feign.Response;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.file.api.feign.FileServiceFeign;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Date;
import java.util.List;
import java.util.Objects;

@Service
public class IUploadServiceImpl implements IUploadService {

    @Autowired
    private IOssService ossService;
    @Autowired
    private IFormTableHeadService formTableHeadService;
    @Autowired
    private IFormTableCodeService formTableCodeService;
    @Autowired
    private FileServiceFeign fileServiceFeign;


    @Override
    public OssFile save(String formId, String ctrlId, MultipartFile file, String bizPath) {
        if (StringUtils.isEmpty(formId)) {
            throw new ResultException("formId不能为空");
        }

        if (file.isEmpty()) {
            throw new ResultException("文件不能为空");
        }

        // 测试阶段可以注释下面这行代码
//        if (StringUtils.isEmpty(ctrlId)) {
//            throw new ResultException("ctrlId不能为空");
//        }

        FormTableHead formTableHead = formTableHeadService.getById(formId);

        OssFile ossFile = ossService.uploadFile(file, bizPath);
        ossFile.setFormId(formId);

        ossFile.setTableName(formTableHead.getTableName());
//        ossFile.setFileType();
        FormTableCode formTableCode = formTableCodeService.getLatestOneByFormId(formId);
        String tableCode = formTableCode.getTableCode();
        //FormVo formVo = JSON.parseObject(tableCode, FormVo.class);
        FormVo formVo = VoUtils.newFormVo(tableCode);
        List<FormComponent> list = formVo.getList();
        for (FormComponent formComponent : list) {
//            if (formComponent.getModel().equals(ctrlId) && formComponent.getType().equals("uploadImg")) {
//                // todo 拿到对应的组件，然后判断是否附件类型
//
//                // 测试代码 此处随便添加一个附件类型
//                ossFile.setFileType(CommonConstant.ZwOrFJ.Fj.getValue());
//                break;
//            }
        }

        // 保存对象，方便以后清理无用文件
        ossService.save(ossFile);
        return ossFile;
    }

    /**
     * 上传并保存
     * @param formId form_table_head -> id || work_instance -> id （流程）
     * @param ctrlId 对应自定义表的该条数据实例ID || work_item -> id （环节）
     * @param file 文件
     * @param bizPath null 自动生成
     * @param fileType 附件来源类型 1、办文 2、邮件 3、意见附件
     * @return /
     */
    @Override
    public OssFile saveToFileService(String formId, String ctrlId, String uploadList, MultipartFile file, String bizPath, String fileType) {
        // 前端是否给出了文件路径，给了就用前端的，没给就后端自己生成
        if (StringUtils.isEmpty(bizPath)) {
            bizPath = DateFormatUtils.format(new Date(), "yyyy/MM/dd");
        }
        if (file.isEmpty()) {
            throw new ResultException("文件不能为空");
        }

        String username = "username";
        // 获取文件名
        String orgName = file.getOriginalFilename();
        assert orgName != null;
//        orgName = CommonUtils.getFileName(orgName);
        String fileExtension = Files.getFileExtension(orgName);
        String filename = IdWorker.getId() + "_" + System.currentTimeMillis() + "." + fileExtension;
        // 上传文件
        fileServiceFeign.uploadFile(username, bizPath, filename, file);

        OssFile ossFile = new OssFile();
        ossFile.setFileName(orgName);
        ossFile.setFilePath(bizPath + "/" + filename);
        ossFile.setFileSuffix(fileExtension);
        // 用于多态关联
        ossFile.setFormId(formId);
        // 自定义表中的数据实例ID
        ossFile.setTableId(ctrlId);
        // 关联对应附件列表
        ossFile.setUploadList(uploadList);
        // 设置表名
        FormTableHead formTableHead = formTableHeadService.getById(formId);
        ossFile.setTableName("/");
        if (formTableHead != null) {
            ossFile.setTableName(formTableHead.getTableName());
        }
        if (StringUtils.isBlank(fileType)) {
            fileType = "0";
        }
        ossFile.setFileType(fileType);
        // 保存对象，方便以后清理无用文件
        ossService.save(ossFile);
        return ossFile;
    }

    @Override
    public void downloadFile(String bizPath, HttpServletResponse response) {
        OutputStream outputStream = null;
        response.setContentType("application/octet-stream");
//        response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(file.getName(), "utf-8"));
//        response.addHeader("Content-Length", "" + file.length());
        try {
            outputStream = response.getOutputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
        String username = "username";
        Response downResponse = fileServiceFeign.downLoadFile(username, bizPath);

        InputStream inputStream = null;
        try {
            Response.Body body = downResponse.body();
            inputStream = body.asInputStream();
            byte[] bytes = new byte[1024];
            int len = 0;
            while ((len = inputStream.read(bytes)) != -1) {
                outputStream.write(bytes, 0, len);
            }
        } catch (Throwable e) {
            e.printStackTrace();
        } finally {
            try {
                inputStream.close();
                outputStream.flush();
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void downloadFiles(String pathsArr, String filenamesArr, HttpServletResponse response) {
        OutputStream outputStream = null;
        InputStream inputStream = null;
        response.setContentType("application/octet-stream");
        try {
            outputStream = response.getOutputStream();
            Response downResponse = fileServiceFeign.downloadFullNameFiles(pathsArr, filenamesArr);
            Response.Body body = downResponse.body();
            inputStream = body.asInputStream();
            byte[] bytes = new byte[1024];
            int len;
            while ((len = inputStream.read(bytes)) != -1) {
                assert outputStream != null;
                outputStream.write(bytes, 0, len);
            }
        } catch (Throwable e) {
            e.printStackTrace();
        } finally {
            try {
                assert inputStream != null;
                inputStream.close();
                assert outputStream != null;
                outputStream.flush();
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * header中获取token，解析得到用户名
     * @return username
     */
    private String getUsername() {
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        DecodedJWT jwt = JWT.decode(request.getHeader(CommonConstant.X_ACCESS_TOKEN));
        return jwt.getClaim("username").asString();
    }

}
